package com.huishi.handler.execute;

import com.huishi.config.FtpFileConfig;
import com.huishi.constant.FTPConstant;
import com.huishi.entity.FileMetaData;
import com.huishi.entity.PlacingFileTask;
import com.huishi.entity.ResponseResult;
import com.huishi.entity.vo.FileMetaDataKeepVO;
import com.huishi.entity.vo.FileMetaDataVO;
import com.huishi.handler.ftp.FTPUtil;
import com.huishi.mapper.FileMetaDataMapper;
import com.huishi.mapper.PlacingFileTaskMapper;
import com.huishi.ui.FileChooserUI;
import com.huishi.util.FileUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.swing.*;
import java.io.File;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Timer;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

@Service
@Slf4j
public class PlacingFilesService {

    @Autowired
    private FTPUtil ftpUtil;

    @Autowired
    private FileMetaDataMapper fileMetaDataMapper;

    @Autowired
    private PlacingFileTaskMapper placingFileTaskMapper;

    @Autowired
    private FileChooserUI fileChooserUI;

    @Autowired
    private FtpFileConfig ftpFileConfig;


    /**
     * 落盘文件：
     * 总量进度条、百分比、
     * 文件数、文件大小、
     * 速率、用时、剩余时间、操作人
     * <p>
     * 文件数、文件大小 这两个是固定的，直接显示固定
     * <p>
     * 下面几个是隔一段时间展示：
     * 速率 数据传输速率 = 传输的数据量 / 传输时间 传输的数据量 / 用时
     * 用时 开始上传到现在的时间间隔，记录一个开始时间，然后隔一段时间和当前时间作差得出用时，返回展示
     * 剩余时间 先估计这些文件落盘总的大概要花多少时间，减去用时
     */
    @Transactional
    public ResponseResult placingFile(FileMetaDataVO fileMetaDataVO, Long unFinishedTaskId) {
        log.info("placingFile service execute...");
        long start = System.currentTimeMillis();// 开始上传时间
        Date uploadTime = new Date();

//        Set<FileMetaData> fileMetaDataSet = new HashSet<>();
//        Set<String> fileSubNames = new HashSet<>();

        // 1、文件落盘ftp
        Path fileDir = Paths.get(fileMetaDataVO.getDirPath());

        // 1.1扫描文件目录得出要落盘的文件绝对路径集合
        List<Path> files;
        long fileTotalSize;
        try {
            log.info("start getFiles");
            Map<String, Object> allFilesInDirectory = FileUtils.getAllFilesInDirectory(fileDir, fileMetaDataVO);
            files = (List<Path>) allFilesInDirectory.get("files"); // 文件路径集合
            fileTotalSize = (long) allFilesInDirectory.get("fileTotalSize"); // 文件总大小

            log.info("end getFiles");
            if (fileTotalSize == 0) return ResponseResult.fail("上传失败，目录为空或文件为空！");
//            fileChooserUI.getSpeedLabel().setText("速率：" + FileUtils.formatFileSize(fileTotalSize) + "/S");
//            fileChooserUI.getTakeTimeLabel().setText("用时：0s");

            log.info("fileTotalSize:{}", fileTotalSize);
            fileChooserUI.setFileNums(files.size());
            fileChooserUI.getFileNumLabel().setText("文件数：" + files.size());
            fileChooserUI.setFileTotalSize((double) fileTotalSize); // 仍然存储总大小，以字节为单位
            String formattedSize = FileUtils.formatFileSize(fileTotalSize);
            fileChooserUI.getFileTotalSizeLabel().setText("文件大小：" + formattedSize);
        } catch (Exception e) {
            log.error("上传失败：", e);
            return ResponseResult.fail(e.getMessage());
        }


        try {
            // 1.2上传文件
            log.info("begin placing file...");
            Timer timer = new Timer();
            FTPUtil.UploadStatus uploadStatus = ftpUtil.uploadFiles(files, fileTotalSize, start, timer);
            timer.cancel();

            if (FTPUtil.UploadStatus.UploadNewFileFailed.equals(uploadStatus)) {
                return ResponseResult.fail("上传文件失败！");
            }
            // 上传完毕
            fileChooserUI.leftTime = 0.0;
            fileChooserUI.leftTimeLabel.setText("剩余时间：0s");
            fileChooserUI.progressBar.setValue(100);

        } catch (Exception e) {
            e.printStackTrace();
            log.error("落盘文件失败：", e);
            return ResponseResult.fail("落盘文件失败！");
        }


        /**
         * 2、文件元数据入库 如果这边报错文件不影响上面文件落盘
         * 文件名相同的文件入库一条文件元数据 FileMetaData
         */
        recordFileMetaData(files, fileMetaDataVO);

        // 3 落盘文件任务信息入库
        recordPlacingTask(fileMetaDataVO, uploadTime, unFinishedTaskId);


        return ResponseResult.success("上传文件成功！", null);
    }

    private void recordPlacingTask(FileMetaDataVO fileMetaDataVO, Date uploadTime, Long unFinishedTaskId) {
        PlacingFileTask placingFileTask = new PlacingFileTask();
        placingFileTask.setDirPath(fileMetaDataVO.getDirPath());
        placingFileTask.setTaskName(fileMetaDataVO.getTaskName());
        placingFileTask.setTargetId(fileMetaDataVO.getTargetId());
        placingFileTask.setPdwFormatId(fileMetaDataVO.getPdwFormatId());
        placingFileTask.setGatherId(fileMetaDataVO.getGatherId());
        placingFileTask.setSystemModelId(fileMetaDataVO.getSystemModelId());
        placingFileTask.setFileNum(fileChooserUI.getFileNums());
        String fileTotalSize = fileChooserUI.getFileTotalSizeLabel().getText().split("：")[1];
        placingFileTask.setFileTotalSize(fileTotalSize);
        placingFileTask.setUseTime(fileChooserUI.takeTime);
        placingFileTask.setIsFinished("1");
        placingFileTask.setUploadTime(uploadTime);
        placingFileTask.setUserName(fileChooserUI.userNameField.getText());
        placingFileTaskMapper.insert(placingFileTask);

        // 4删除未完成任务
        if (unFinishedTaskId != null) placingFileTaskMapper.deleteByPrimaryKey(unFinishedTaskId);
    }

    private void recordFileMetaData(List<Path> files, FileMetaDataVO fileMetaDataVO) {
        List<String> processedFiles = new ArrayList<>();

        String fileName;
        Map<String, FileMetaDataKeepVO> fileMetaDataMap = new HashMap<>();
        for (Path file : files) {
            String fileFullName = file.getFileName().toString();
            // 不带后缀
            fileName = fileFullName.substring(0, fileFullName.lastIndexOf("."));

            if (processedFiles.contains(fileName)) {
                FileMetaDataKeepVO fileMetaDataKeepVO = fileMetaDataMap.get(fileName);
                long newSize = fileMetaDataKeepVO.getFileSize() + new File(file.toAbsolutePath().toString()).length();
                fileMetaDataKeepVO.setFileSize(newSize);
                continue;
            }
            processedFiles.add(fileName);

            FileMetaDataKeepVO fileMetaDataKeepVO = null;
            try {
                fileMetaDataKeepVO = completeFileMetaDataVO(file, fileMetaDataVO);
            } catch (ParseException e) {
                log.error("{}--文件解析元数据失败", fileName, e);
            }

            // 自定义字段
            Map<Integer, JTextField> customColumns = fileMetaDataVO.getCustomColumns();
            for (Integer key : customColumns.keySet()) {
                if (key == 1) fileMetaDataKeepVO.setCustomColumn1(customColumns.get(key).getText());
                else if (key == 2) fileMetaDataKeepVO.setCustomColumn2(customColumns.get(key).getText());
                else if (key == 3) fileMetaDataKeepVO.setCustomColumn3(customColumns.get(key).getText());
                else if (key == 4) fileMetaDataKeepVO.setCustomColumn4(customColumns.get(key).getText());
                else if (key == 5) fileMetaDataKeepVO.setCustomColumn5(customColumns.get(key).getText());
                else if (key == 6) fileMetaDataKeepVO.setCustomColumn6(customColumns.get(key).getText());
            }

            fileMetaDataMap.put(fileName, fileMetaDataKeepVO);

        }

        for (FileMetaDataKeepVO metaDataKeepVO : fileMetaDataMap.values()) {
            FileMetaData fileMetaData = new FileMetaData();
            BeanUtils.copyProperties(metaDataKeepVO, fileMetaData);
            fileMetaData.setFileSize(FileUtils.formatFileSize(metaDataKeepVO.getFileSize()));
            fileMetaDataMapper.insert(fileMetaData);
        }
    }

    /**
     * 完善上传文件元数据信息
     * <p>
     * 入库要素：ID、采集地点ID、系统型号ID、目标对象（可配置、也可不配置）、采集时间（从文件名中获取）、
     * 中心频率、脉冲个数、入库时间（当前时间）、pdw格式、文件名、文件大小、文件位置、创建人（登入用户）
     * <p>
     * 2022_05_22_10_38_29_281_I_9600MHz_43803
     * 采集时间（从文件名中获取）：2022_05_22_10_38_29_281
     * 中心频率:9600MHz
     * 脉冲个数：43803
     *
     * @param file
     * @param fileMetaDataVO
     * @return
     */
    private FileMetaData completeFileMetaData(Path file, FileMetaDataVO fileMetaDataVO) throws ParseException {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy_MM_dd_HH_mm_ss_SS");
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy_MM_dd_HH_mm_ss_SSS");

        FileMetaData fileMetaData = new FileMetaData();
        BeanUtils.copyProperties(fileMetaDataVO, fileMetaData);

        // 解析文件名
        String fileName = file.getFileName().toString();
        // 定义正则表达式
        String pattern = "(\\d{4}_\\d{2}_\\d{2}_\\d{2}_\\d{2}_\\d{2}_\\d{3})_I_(\\d+MHz)_(\\d+)";
        // 创建 Pattern 对象
        Pattern r = Pattern.compile(pattern);
        // 创建 Matcher 对象
        Matcher m = r.matcher(fileName);
        // 如果匹配成功，则提取信息
        if (m.find()) {
            fileMetaData.setGatherTime(LocalDateTime.parse(m.group(1), formatter));
            fileMetaData.setCenterFreq(m.group(2));
            fileMetaData.setPulseNum(Integer.valueOf(m.group(3)));
        } else {
            log.info("文件名格式不匹配");
        }

        fileMetaData.setInTime(LocalDateTime.now());
        String fileNameSub = fileName.substring(0, fileName.lastIndexOf("."));        // 不带后缀
        fileMetaData.setFileName(fileNameSub);

        String fileSize = FileUtils.formatFileSize(new File(file.toAbsolutePath().toString()).length());
        fileMetaData.setFileSize(fileSize);
        fileMetaData.setFileLocation(ftpFileConfig.getDatPlsFilePath() + fileNameSub);
        fileMetaData.setFileSuffix(fileMetaDataVO.getSystemModel().getDataFormat());
//        fileMetaData.setCreatedBy();

        return fileMetaData;
    }

    private FileMetaDataKeepVO completeFileMetaDataVO(Path file, FileMetaDataVO fileMetaDataVO) throws ParseException {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy_MM_dd_HH_mm_ss_SS");
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy_MM_dd_HH_mm_ss_SSS");

        FileMetaDataKeepVO fileMetaDataKeepVO = new FileMetaDataKeepVO();
        BeanUtils.copyProperties(fileMetaDataVO, fileMetaDataKeepVO);
        fileMetaDataKeepVO.setDicts(fileMetaDataVO);

        // 解析文件名
        String fileName = file.getFileName().toString();
        // 定义正则表达式
        String pattern = "(\\d{4}_\\d{2}_\\d{2}_\\d{2}_\\d{2}_\\d{2}_\\d{3})_I_(\\d+MHz)_(\\d+)";
        // 创建 Pattern 对象
        Pattern r = Pattern.compile(pattern);
        // 创建 Matcher 对象
        Matcher m = r.matcher(fileName);
        // 如果匹配成功，则提取信息
        if (m.find()) {
            fileMetaDataKeepVO.setGatherTime(LocalDateTime.parse(m.group(1), formatter));
            fileMetaDataKeepVO.setCenterFreq(m.group(2));
            fileMetaDataKeepVO.setPulseNum(Integer.valueOf(m.group(3)));
        } else {
            log.info("文件名格式不匹配");
        }

        fileMetaDataKeepVO.setInTime(LocalDateTime.now());
        String fileNameSub = fileName.substring(0, fileName.lastIndexOf("."));        // 不带后缀
        fileMetaDataKeepVO.setFileName(fileNameSub);

        fileMetaDataKeepVO.setFileSize(new File(file.toAbsolutePath().toString()).length());
        fileMetaDataKeepVO.setFileLocation(ftpFileConfig.getDatPlsFilePath() + fileNameSub);
        fileMetaDataKeepVO.setFileSuffix(fileMetaDataVO.getSystemModel().getDataFormat());

        return fileMetaDataKeepVO;
    }
}
